package com.tool.cn.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * zip压缩工具类
 * 
 * @author wangzh 2017年10月17日 下午3:54:19
 */
public class ZipUtil {
	private static final Log log = LogFactory.getLog(ZipUtil.class);
	
	/**
	 * 压缩文件为gz
	 * @param sourceFileName
	 * @param gzipFileName
	 */
	public static void GzipFile(String sourceFileName, String gzipFileName) {
		try {
			// 建立gzip压缩文件输入流
			File sourceFile = new File(sourceFileName);
			// 创建zip输出流
			GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(gzipFileName));
		
			FileInputStream fos = new FileInputStream(sourceFile);
			BufferedInputStream bis = new BufferedInputStream(fos);

			int tag;
			// 将源文件写入到zip文件中
			while ((tag = bis.read()) != -1) {
				out.write(tag);
			}
			
			bis.close();
			out.flush();
			out.close();
		} catch (Exception ex) {
			System.err.println(ex.toString());
		}
	}
	
	/**
	 * 文件或文件夹tar打包
	 * @param sourceFile  源文件路径
	 * @param os  文件流
	 * @param basePath 归档包路径
	 */
	public static void tarFile(File sourceFile,TarArchiveOutputStream os,String basePath){
		try {
//			TarArchiveOutputStream os = new TarArchiveOutputStream(new FileOutputStream(tarFile));
			if(sourceFile.isDirectory()){
				File[] fileList = sourceFile.listFiles();
				if(fileList.length==0){
			        
					os.putArchiveEntry(new TarArchiveEntry(basePath+File.separator));
					os.closeArchiveEntry();
				}else{
					for (File file : fileList) {
						tarFile(file,os,basePath+File.separator+file.getName());
					}
				}
				
			}else{
				TarArchiveEntry entry = new TarArchiveEntry(basePath);  
			    entry.setSize(sourceFile.length());  
			    os.putArchiveEntry(entry);  
			    
			    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));  
			    int count;  
			    byte data[] = new byte[1024];  
			    while ((count = bis.read(data, 0, 1024)) != -1) {  
			        os.write(data, 0, count);  
			    }  
			  
			    bis.close();  
				os.closeArchiveEntry();
				
			}
			
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 文件或文件夹打包为zip格式
	 * @param zipFileName
	 * @param sourceFileName
	 */
	public static void zip(String zipFileName, String sourceFileName) {
		try {
			// File zipFile = new File(zipFileName);
			log.info("压缩中...");

			// 创建zip输出流
			ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));

			// 创建缓冲输出流
			BufferedOutputStream bos = new BufferedOutputStream(out);

			File sourceFile = new File(sourceFileName);

			// 调用函数
			compress(out, bos, sourceFile, sourceFile.getName());

			bos.close();
			out.close();
			log.info("压缩完成");
		} catch (FileNotFoundException e) {
			log.error(e, e);
		} catch (IOException e) {
			log.error(e, e);
		}

	}

	private static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base) {
		try {
			// 如果路径为目录（文件夹）
			if (sourceFile.isDirectory()) {

				// 取出文件夹中的文件（或子文件夹）
				File[] flist = sourceFile.listFiles();

				if (flist.length == 0)// 如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
				{
					log.info(base + "/");
					out.putNextEntry(new ZipEntry(base +File.separator));
				} else// 如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
				{
					for (int i = 0; i < flist.length; i++) {
						compress(out, bos, flist[i], base +File.separator + flist[i].getName());
					}
				}
			} else {
				out.putNextEntry(new ZipEntry(base));
				FileInputStream fos = new FileInputStream(sourceFile);
				BufferedInputStream bis = new BufferedInputStream(fos);

				int tag;
				log.info(base);
				// 将源文件写入到zip文件中
				while ((tag = bis.read()) != -1) {
					out.write(tag);
				}
				bis.close();
				fos.close();
			}
		} catch (FileNotFoundException e) {
			log.error(e, e);
		} catch (IOException e) {
			log.error(e, e);
		}
	}

}
